using System;

namespace DSP.MathLibrary
{
    public class ComplexNumber
    {
        public ComplexNumber(double re, double im)
        {
            _re = re;
            _im = im;
            if ((re != 0) && (im != 0))
            {
                _arg = Math.Atan(im / re);
            }
            else
            {
                _arg = Math.PI / 2;
            }
            _mod = Math.Sqrt(re * re + im * im);
        }

        private double _re;
        private double _im;
        private double _arg;
        private double _mod;

        public double Re
        {
            get { return _re; }
        }

        public double Im
        {
            get { return _im; }
        }

        public double Arg
        {
            get { return _arg; }
        }

        public double Mod
        {
            get { return _mod; }
        }


        public static ComplexNumber operator -(ComplexNumber cm1, ComplexNumber cm2)
        {
            return new ComplexNumber(cm1.Re - cm2.Re, cm1.Im - cm2.Im);
        }

        public static ComplexNumber operator -(ComplexNumber cm)
        {
            return new ComplexNumber(-cm.Re, -cm.Im);
        }

        public static ComplexNumber operator +(ComplexNumber cm1, ComplexNumber cm2)
        {
            return new ComplexNumber(cm1.Re + cm2.Re, cm1.Im + cm2.Im);
        }

        public static ComplexNumber operator *(ComplexNumber cm1, ComplexNumber cm2)
        {
            return new ComplexNumber(cm1.Re * cm2.Re - cm1.Im * cm2.Im, cm1.Im * cm2.Re + cm1.Re * cm2.Im);
        }

        public static ComplexNumber operator *(ComplexNumber cm1, double d)
        {
            return new ComplexNumber(cm1.Re * d, cm1.Im * d);
        }

        public static ComplexNumber operator /(ComplexNumber cm1, ComplexNumber cm2)
        {
            double r = (cm1.Re * cm2.Re + cm1.Im * cm2.Im) / (cm2.Re * cm2.Re + cm2.Im * cm2.Im);
            double i = (cm1.Im * cm2.Re - cm1.Re * cm2.Im) / (cm2.Re * cm2.Re + cm2.Im * cm2.Im);
            return new ComplexNumber(r, i);
        }

        public static bool operator ==(ComplexNumber cm1, ComplexNumber cm2)
        {
            if (cm1.Im != cm2.Im) return false;
            else if (cm1.Re != cm2.Re) return false;
            return true;
        }

        public static bool operator !=(ComplexNumber cm1, ComplexNumber cm2)
        {
            return !(cm1 == cm2);
        }

        public static ComplexNumber inv(ComplexNumber cm)
        {
            return new ComplexNumber(cm.Re, -cm.Im);
        }

        public static ComplexNumber Exp(ComplexNumber cn)
        {
            double re = Math.Exp(cn.Re) * Math.Cos(cn.Im);
            double im = Math.Exp(cn.Re) * Math.Sin(cn.Im);
            return new ComplexNumber(re, im);
        }


    }
}
